from prg.command_info import CommandInfo
from prg.proc.udp_thread import UdpLink
from prg.entity.arg_entity import ArgBase
from prg.common.common_base import CommonBase
from prg.bll.authority_bll import AuthorityBll
from prg.bll.udp_bll import UdpBll
from prg.common.object_message import MessageBase
from prg.entity.public_entity import PublicEntity
from prg.bll.config_bll import ConfigBll


class ConnectClient(MessageBase):
    def __init__(self, from_addr, to_addr, local_port, task_id):
        super().__init__(name="Connect")
        self.user = AuthorityBll.instance()
        self.addr = PublicEntity.instance().addr
        self.command_queue = PublicEntity.instance().command
        self.udp = PublicEntity.instance().udp
        self.host = ConfigBll.instance().get_host()
        self.from_addr = from_addr
        self.to_addr = to_addr
        self.local_port = local_port
        self.task_id = task_id
        self.create_semaphore(value=2)

    def link_udp(self, addr_name):
        udp_port = UdpBll.instance().get_port()
        register_item = self.addr[addr_name]
        user_inf = self.user.get_user(addr_name)
        udp = UdpLink(addr=register_item, port=udp_port, aut=user_inf)
        self.udp[addr_name] = udp
        udp.start()
        arg_dict = dict()
        arg_dict["name"] = addr_name
        arg_dict["ip"] = self.host.ip
        arg_dict["port"] = udp_port
        self.create_send_cmd(addr=register_item, cmd="udp", arg_dict=arg_dict)

    def create_send_cmd(self, addr, cmd, arg_dict):
        user_inf = self.user.get_user(addr.get_name())
        arg = ArgBase()
        arg.sign = user_inf.password
        arg.arg_dict = arg_dict
        arg_str = CommonBase.aes_encryption_json(key=user_inf.aes, entity=arg)
        cmd_item = CommandInfo(socket_item=addr.get_socket(), command=cmd, name=addr.get_name(), arg=arg_str)
        self.command_queue.put(cmd_item)

    def entry(self):
        self.link_udp(addr_name=self.from_addr)
        self.link_udp(addr_name=self.to_addr)
        from_item = self.addr[self.from_addr]
        to_item = self.addr[self.to_addr]
        self.acquire()
        to_inf = to_item.get_udp_addr()
        frm_inf = from_item.get_udp_addr()
        frm_dict = {"name": self.to_addr, "ip": to_inf[0], "port": to_inf[1], "local": self.local_port, "task": self.task_id}
        to_dict = {"name": self.from_addr, "ip": frm_inf[0], "port": frm_inf[1], "local": self.local_port, "task": self.task_id}
        self.create_send_cmd(addr=from_item, cmd="link", arg_dict=frm_dict)
        self.create_send_cmd(addr=to_item, cmd="link-to", arg_dict=to_dict)
        print("link %s -> %s command send" % (self.from_addr, self.to_addr))


